import multiprocessing
import socket
import threading

import cv2
import numpy as np

# 中心位置所在图片百分比
center_x = 0.5
center_y = 200 / 720

# 输入像素
high = 720
width = 960
cx = width / 2
cy = high / 2

# 相机焦距(像素)
f = 900

# 圆半径(cm)
cr = 40

b_deal1 = 11
b_deal2 = 7
cr1 = 200
cr2 = 75
min_r = 100
max_r = 300
circle_color = (255, 255, 255)

font = cv2.FONT_HERSHEY_SIMPLEX
font_scale = 1.5
font_color = (255, 255, 255)
line_thickness = 2
place = (20, 60)
Text = "Distance:{:.0f}cm"


def identify(qi, qb, qo, qm):
    img = None
    g_img = None
    b_img = None
    out_img = None
    x = -1
    y = -1
    r = -1
    d = -1
    dx = -1
    dy = -1
    while True:
        print("___")
        img = qi.get()
        if img is None:
            continue
        g_img = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
        b_img = cv2.adaptiveThreshold(g_img, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY, b_deal1,
                                      b_deal2)  # 自动阈值二值化
        circles = cv2.HoughCircles(b_img, cv2.HOUGH_GRADIENT, 1, 170, param1=cr1, param2=cr2, minRadius=min_r,
                                   maxRadius=max_r)
        if circles is not None:
            circles = np.round(circles[0, :]).astype("int")
            (x, y, r) = max(circles, key=lambda k: k[2])
            d = cr / r * f
            mx = x - cx
            dx = mx / f * d
            my = y - cy
            dy = my / f * d
        out_img = g_img
        if x >= 0 and y >= 0 and r >= 0:
            cv2.putText(out_img, Text.format(d), place, font, font_scale, font_color,
                        line_thickness, cv2.LINE_AA)
            cv2.circle(out_img, (x, y), r, circle_color, 4)
        qb.put(b_img)
        qo.put(out_img)
        qm.put((dx, dy, d))


class Detect:
    def __init__(self):
        self.i_q = multiprocessing.Queue()
        self.b_q = multiprocessing.Queue()
        self.o_q = multiprocessing.Queue()
        self.m_q = multiprocessing.Queue()
        self.process = multiprocessing.Process(target=identify, args=(self.i_q, self.b_q, self.o_q, self.m_q))

    def start(self):
        self.process.start()

    def get_res(self, img):
        self.i_q.put(img)
        return self.b_q.get(), self.o_q.get(), self.m_q.get()


class Tool:
    b_img = None
    o_img = None
    dx = -1
    dy = -1
    d = -1

    def __init__(self, video=None):
        self.video = video
        self.tool = Detect()
        self.thread = threading.Thread(target=self.get_resp)
        self.show_thread = threading.Thread(target=self.show)

    def start(self):
        self.tool.start()
        self.thread.start()

    def get_resp(self):
        while True:
            # print(self.video.img)
            new_img = self.video.img
            if new_img is None:
                continue
            self.b_img, self.o_img, (self.dx, self.dy, self.d) = self.tool.get_res(new_img)
            # print(self.tool.get_res(self.video.img))

    def show(self):
        while True:
            if self.o_img is None:
                continue
            cv2.imshow('show', self.o_img)
            cv2.waitKey(1)

    def start_show(self):
        self.show_thread.start()


class test:
    cmd_ip = (socket.gethostbyname(socket.gethostname()))
    cmd_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)  # socket for sending cmd
    cmd_sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    cmd_sock.bind((cmd_ip, 8890))
    video_sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)  # socket for sending cmd
    video_sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    video_sock.bind(('0.0.0.0', 11111))

    img = None

    def update(self):
        cot = 2
        while True:
            if cot == 1:
                self.img = cv2.imread('2.png')
                cot = 2
            elif cot == 2:
                self.img = cv2.imread('1.png')
                cot = 1
            self.video_sock.recvfrom(10240)

    def start(self):
        self.cmd_sock.sendto('command'.encode('gbk'), ('192.168.10.1', 8889))
        self.cmd_sock.sendto('streamon'.encode('gbk'), ('192.168.10.1', 8889))
        thread = threading.Thread(target=self.update)
        thread.start()


if __name__ == '__main__':
    video = test()
    video.start()
    tool = Tool(video)
    tool.start()
    tool.start_show()
    tool.thread.join()
